所謂最小化可變性,就是把類別盡量設計成immutable,immutable類別是指,在類別實體化之後,類別裡面的資料不能再被更動修改,因此,相較於mutable類別狀態的不確定性,immutable類別不管在設計、實作和使用上,都是比較簡潔和安全的,而且如果系統是multi-thread的設計,immutable類別也可以確保thread-safe,避免同一個物件對每個thread的狀態都不一致。而要如何設計immutable類別,我們可以遵循下面的規則:
final
防止被繼承。final
:這樣就可以避免其他使用者去更動欄位的值,當然,也可以確保thread之間的物件狀態不會被更動,造成資訊不一致的狀況。private
:如前面的曾經提過,雖然類別把欄位加了final
屬性,但如果該欄位的值是reference而且是mutable,還是可以修改該欄位的狀態,為了避免這種情況,應該把欄位設為private
。而如果物件的狀態需要改變,可以回傳一個新的物件,既可避免原本的物件狀態被改變,又可以滿足新需求,下面的範例示範了,如何在狀態需要改變的時候,產生一個新的物件。
public final class Point {
private final int x;
private final int y;
// Constructor
public Point(int x, int y) {
this.x = x;
this.y = y;
}
// Getter methods
public int getX() {
return x;
}
public int getY() {
return y;
}
// Method to move the point
public Point move(int deltaX, int deltaY) {
return new Point(this.x + deltaX, this.y + deltaY);
}
@Override
public String toString() {
return "Point{" + "x=" + x + ", y=" + y + '}';
}
public static void main(String[] args) {
// Create a new Point
Point p1 = new Point(0, 0);
System.out.println("Original Point: " + p1);
// Move the Point to a new location
Point p2 = p1.move(5, 10);
System.out.println("Moved Point: " + p2);
// Verify that the original Point remains unchanged
System.out.println("Original Point after move: " + p1);
}
}
這樣可以確保物件是immutable,而且是thread-safe,不需要額外做同步。當然,除了這個方式之外,明天再介紹更多的方式讓物件保持immutable,也說說immutable物件的缺點,以及有什麼解法。